package com.AdvancedDemos.泛型;

import java.util.ArrayList;

public class Generic {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        /**
         * 泛型的作用:
         * 泛型提供了在编译阶段约束所能操作的数据类型,并自动进行检查的能力!
         * 这样可以避免强制类型转换,及其可能出现的异常
         * <p>
         * 泛型的本质:
         * 把具体的数据类型作为参数传递给类型变量
         */

        /* 泛型类格式:
         *
         *  修饰符 class 类名<类型变量,类型变量, ... >{
         *      ........
         * }
         * public class ArrayList<E>{
         *      ........
         * }
         */

        //使用时如果不指定泛型,则默认E是Object类型
        MyArrayList list1 = new MyArrayList();
        Object o = null;
        list1.add(o);

        //指定泛型
        MyArrayList<String> list2 = new MyArrayList<>();
        list2.add("java1");
        list2.add("java2");
        String temp = list2.get(1);
        System.out.println(temp);

        //多个泛型的泛型类
        Myclass<String, String> c = new Myclass<>();
        String e = "1", t = "2";
        c.put(e, t);

        Myclass<Animal, Cat> c1 = new Myclass<>();
        Animal animal = new Animal();
        Cat cat = new Cat();
        c1.put(animal, cat);//Animal e,Cat t

        //指定继承关系的泛型
        Myclass2<Dog> c2 = new Myclass2<>();
        Myclass2<Animal> c3 = new Myclass2<>();

        /**
         * 注意点:
         * 1.泛型是工作在编译阶段的,只在编写代码阶段,约束程序员只能写某种类型,一旦程序编译成.class字节码文件,当中就不存在泛型了,如ArrayList<String> list中的<String>就消失了,list.get(i)得到的都是Object类型,.class文件中都是写成强转成(String)再赋给String str的,这就是"泛型擦除"
         *
         * 2.泛型不支持基本数据类型,只能支持引用类型,基本类型自动装箱成包装类 int -> Integer , double -> Double ...
         *
         */


    }
}

/**
 * 泛型类可以作为父类被继承
 */
class Zi1 extends MyArrayList<Integer> {
    //子类继承泛型类时,应当指定父类的泛型
}

class Zi2<E> extends MyArrayList<E> {
    //或者将子类也写成泛型类,父类中的泛型由新建子类对象时给出
}

/**
 * 单泛型类
 *
 * @param <E>
 */
class MyArrayList<E> {//通常类型变量用E:element T:type K:key V:value Q:query
    E e;

    private Object[] arr = new Object[10];//使用Object数组就可以承接所有类型的数据
    private int size;//记录当前位置,默认初值是0

    public boolean add(E e) {//形参的类型取决于泛型类型
        arr[size++] = e;
        return true;
    }

    public E get(int index) {
//        if (arr[index] instanceof E) //报错,泛型用不了instanceof
        return (E) arr[index];
//        }
//        return null;
    }
}

/**
 * 多泛型类
 *
 * @param <E>
 * @param <T>
 */
class Myclass<E, T> {
    public void put(E e, T t) {

    }
}

class Animal {
}

class Cat {
}

/**
 * 指定继承关系的泛型类
 *
 * @param <E>
 */
class Myclass2<E extends Animal> {//此处的泛型指定为必须是继承了Animal类的一个子类型,或者就是Animal本身

}

class Dog extends Animal {

}


/**
 * 泛型接口
 *
 * @param <T>
 */
interface SchoolData<T> {//接口中的泛型与类中的泛型一样,也可要求继承某个类 T extends Animal

    void add(T t);

    ArrayList<T> getByName(String name);
}

class Teacher {

}

class teacherData implements SchoolData<Teacher> {

    @Override
    public void add(Teacher teacher) {

    }

    @Override
    public ArrayList<Teacher> getByName(String name) {
        return null;
    }
}

class Student {

}

class studentData implements SchoolData<Student> {

    @Override
    public void add(Student student) {

    }

    @Override
    public ArrayList<Student> getByName(String name) {
        return null;
    }
}











